<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自己</title>
</head>
<body>
    <script>

        /*
        * 1. promiseCbk的回调函数
        * 2. 解决resolve,reject函数内部的this问题
        * 3. 解决再一个promise中多次调用resolve/reject的问题
        * 4. 在promise执行过程中的异常捕捉
        * 5. then方法的实现
        * 6. resolve/reject方法的异步执行
        * 7. resolve/reject异常捕捉及处理方式
        * 8. 延时成功或者失败的状态更改
        * 9. then的连缀调用
        * 10. resolve方法的实现
        * 11. reject方法的实现
        * 12. all方法的实现
        * 13. race方法的实现
        * 14. then的穿透传递
        **/

        class MyPromise{
            static FULFILLED = 'fulfilled';
            static PENDING = 'pending';
            static REJECTED = 'rejected';
            constructor(promiseCbk) {
                // 开始状态
                this.state = MyPromise.PENDING;
                // 参数内容
                this.value = null;
                // 收集异步任务
                this.allCbk = [];
                // 容错
                try{
                    // 开始传递参数
                    promiseCbk(this.resolve.bind(this), this.reject.bind(this))
                }catch(error) {
                    this.reject(error)
                }
                
            }
            // 成功的方法
            resolve(value) {
                // 先判断状态
                if (this.state === MyPromise.PENDING) {
                    // 改为成功的状态
                    this.state = MyPromise.FULFILLED;
                    // 保存内容
                    this.value = value;
                    // 执行异步任务
                    setTimeout(() => {
                        this.allCbk.forEach(item => {
                            item.onFulfilled(this.value)
                        })
                    })
                }
                
            }
            // 失败的方法
            reject(value) {
                // 先判断状态
                if (this.state === MyPromise.PENDING) {
                    // 改为失败的状态
                    this.state = MyPromise.REJECTED;
                    // 保存内容
                    this.value = value
                    // 执行异步任务
                    setTimeout(() => {
                        this.allCbk.forEach(item => {
                            item.onRejected(this.value)
                        })
                    })
                }
            }
            // 成功的对应方法
            then(onFulfilled, onRejected) {
                // 判断是否链式调用
                if (typeof onFulfilled !== 'function') {
                    onFulfilled = () => this.value
                }
                if (typeof onRejected !== 'function') {
                    onRejected = () => this.value
                }
                return new MyPromise((resolve, reject) => {
                    if (this.state === MyPromise.PENDING) {
                        this.allCbk.push({
                            onFulfilled: (value) => {
                                try{
                                    let res = onFulfilled(this.value);
                                    resolve(res)
                                }catch(error) {
                                    onRejected(error)
                                }
                            },
                            onRejected: (value) => {
                                try{
                                    let res = onRejected(this.value)
                                    resolve(res)
                                }catch(error) {
                                    onRejected(error)
                                }
                            }
                        })
                    }
                    if (this.state === MyPromise.FULFILLED) {
                        setTimeout(() => {
                            try{
                                let res = onFulfilled(this.value);
                                resolve(res)
                            }catch(error){
                                onRejected(error)
                            }
                        })
                    }
                    if (this.state === MyPromise.REJECTED) {
                        setTimeout(() => {
                            try{
                                let res = onRejected(this.value)
                                resolve(res)
                            }catch(error) {
                                onRejected(error)
                            }
                        })
                    }
                })
            }
            // promise简写
            static resolve(value) {
                return new MyPromise((resolve, reject) => {
                    if (value instanceof MyPromise) {
                        value.then(resolve, reject)
                    } else {
                        resolve(value)
                    }
                })
            }
            // promise简写
            static reject(value) {
                return new MyPromise((resolve, reject) => {
                    if (value instanceof MyPromise) {
                        value.then(resolve, reject)
                    } else {
                        reject(value)
                    }
                })
            }
            // 执行所有的promise
            static all(promises) {
                // 任务收集器
                const allReslut = [];
                return new MyPromise((resolve, reject) => {
                    promises.forEach(item => {
                        item.then(trueRes => {
                            allReslut.push(trueRes);
                            if (allReslut.length === promises.length) {
                                resolve(allReslut)
                            }
                        }, falseRes => {
                            reject(falseRes)
                        })
                    })
                })
            }
            // 执行第一个成功的then方法
            static race(promises) {
                return new MyPromise((resolve, reject) => {
                    promises.forEach(item => {
                        item.then(trueRes => {
                            resolve(trueRes)
                        }, falseRes => {
                            reject(falseRes)
                        })
                    })
                })
            }
        }

        // 咱们的promise就大功告成了


        // let p1 = new Promise((resolve, reject) => {
        //     setTimeout(() => {
        //         resolve(1)
        //     }, 2000)
        // })
        // let p2 = new Promise((resolve, reject) => {
        //     setTimeout(() => {
        //         resolve(2)
        //     }, 1000)
        // })

        // MyPromise.race([p1, p2]).then(res => {
        //     console.log('res', res)
        // }, error => {
        //     console.log('err', error)
        // })

        // MyPromise.reject(new MyPromise((resolve, reject) => reject(3))).then(res => {
        //     console.log(res, 'res')
        // }, error => {
        //     console.log('error', error)
        // })
        // let promiseRes = new MyPromise((resolve, reject) => {
        //     resolve(2)
        // })
        // .then()
        // .then(successRes => {
        //     console.log('successRes', successRes)
        //     return 2
        // }, error => {
        //     console.log('error', error)
        //     return 34
        // })
        // .then(againTrue => {
        //     console.log(againTrue, 'againTrue')
        // }, againFalse => {

        // })
    </script>
</body>
</html>